package com.lck.blogmanager.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lck.blogmanager.Enum.*;
import com.lck.blogmanager.entity.*;
import com.lck.blogmanager.exception.BusinessException;
import com.lck.blogmanager.mapper.*;
import com.lck.blogmanager.req.*;
import com.lck.blogmanager.res.BlogUserDetailRes;
import com.lck.blogmanager.res.DetailBlogRes;
import com.lck.blogmanager.res.PageBlogRes;
import com.lck.blogmanager.res.UserBlogListRes;
import com.lck.blogmanager.service.BlogService;
import com.lck.blogmanager.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @author wyq
 * @version v1.0.0
 * @explain
 * @date 2024/4/7 17:18
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class BlogServiceImpl extends ServiceImpl<BlogMapper, BlogEntity> implements BlogService {


    private final UserMapper userMapper;

    private final TagMapper tagMapper;

    private final AuditMapper auditMapper;

    private final LikeMapper likeMapper;

    private final CollectMapper collectMapper;

    private final BlogCommentMapper blogCommentMapper;


    @Override
    public Integer addBlog(AddBlogReq req) {
        BlogEntity blog = new BlogEntity();
        BeanUtils.copyProperties(req,blog);
        blog.setUserId(SecurityUtils.getUserId())
                .setStatus(BlogStatusEnum.COMMIT.getValue())
                .setViewCount(0)
                .setLikeCount(0)
                .setCollectCount(0)
                .setCreateTime(LocalDateTime.now())
                .setUpdateTime(LocalDateTime.now());
        this.save(blog);
        return blog.getId();
    }

    @Override
    public void updateBlog(UpdateBlogReq req) {
        QueryWrapper<BlogEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(BlogEntity::getId,req.getId());
        BlogEntity entity = this.getBaseMapper().selectById(req.getId());
        if(req.getTotal()!=null&&req.getTotal()!=""){
            entity.setTotal(req.getTotal());
        }
        if(req.getBody()!=null&&req.getBody()!=""){
            entity.setBody(req.getBody());
        }
        if(req.getTagId()!=null){
            entity.setTagId(req.getTagId());
        }
        entity.setUpdateTime(LocalDateTime.now());
        entity.setStatus(BlogStatusEnum.COMMIT.getValue());
        this.saveOrUpdate(entity);
    }

    @Override
    public void deleteBlog(DeleteBlogReq req) {
        this.removeById(req.getId());
    }

    @Override
    public Page<PageBlogRes> pageBlog(PageBlogReq req) {
        Page page = new Page(req.getPageNum(),req.getPageSize());
        Page<PageBlogRes> result = this.getBaseMapper().pageBlog(req,page);
        return result;

    }

    @Override
    public DetailBlogRes detailBlog(Integer blogId) {
        //查博客
        BlogEntity blog = this.getBaseMapper().selectById(blogId);
        //查关联的用户
        QueryWrapper<UserEntity> userWrapper = new QueryWrapper<>();
        userWrapper.lambda().eq(UserEntity::getId,blog.getUserId());
        UserEntity user = userMapper.selectById(blog.getUserId());
        //查关联的标签名
        TagEntity tag = tagMapper.selectById(blog.getTagId());
        //查审核记录
        QueryWrapper<AuditEntity> auditWrapper = new QueryWrapper<>();
        auditWrapper.lambda().eq(AuditEntity::getRelationId,blogId)
                .eq(AuditEntity::getType,AuditTypeEnum.BLOG.getValue());
        List<AuditEntity> auditEntities = auditMapper.selectList(auditWrapper);
        DetailBlogRes res = new DetailBlogRes();
        BeanUtils.copyProperties(blog,res);
        res.setAuditRecords(auditEntities);
        res.setTagName(tag.getTagName());
        res.setUserName(user.getName());
        return res;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditBlog(AuditBlogReq req) {
        //插入审核记录
        AuditEntity audit = new AuditEntity();
        audit.setType(AuditTypeEnum.BLOG.getValue());
        audit.setRelationId(req.getId());
        audit.setResult(req.getResult());
        if(audit.getResult()==1){
            audit.setMessage("通过");
        }else {
            audit.setMessage(req.getReason());
        }
        audit.setCreateTime(LocalDateTime.now());
        auditMapper.insert(audit);
        //改博客的状态和博客的审核时间
        BlogEntity blog = this.getBaseMapper().selectById(req.getId());
        blog.setStatus(req.getResult());
        blog.setAuditTime(LocalDateTime.now());
        this.saveOrUpdate(blog);
    }

    @Override
    public Page<UserBlogListRes> userList(UserBlogListReq req) {
        Page page = new Page(req.getPageNum(),req.getPageSize());
        Page<UserBlogListRes> info = getBaseMapper().userList(req,page);
        return info;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BlogUserDetailRes userDetail(Integer blogId) {
        new Thread(()->viewBlog(blogId)).start();
        BlogUserDetailRes res = new BlogUserDetailRes();
        Integer userId = SecurityUtils.getUserId();
        res.setUserId(userId);
        //先查博客本体
        BlogEntity blog = this.getBaseMapper().selectById(blogId);
        if(blog==null){
            throw new BusinessException("博客实体不存在");
        }
        res.setBlog(blog);
        //再查点赞信息
        QueryWrapper<LikeEntity> likeWrapper = new QueryWrapper<>();
        likeWrapper.lambda().eq(LikeEntity::getUserId,userId)
                .eq(LikeEntity::getType, LikeRelationTypeEnum.BLOG.getValue())
                .eq(LikeEntity::getRelationId,blogId);
        Long likeCount = likeMapper.selectCount(likeWrapper);
        if(likeCount>0){
            res.setIsLike(CommonEnum.YES.getValue());
        }else {
            res.setIsLike(CommonEnum.NO.getValue());
        }
        //收藏信息
        QueryWrapper<CollectEntity> countWrapper = new QueryWrapper<>();
        countWrapper.lambda().eq(CollectEntity::getUserId,userId)
                .eq(CollectEntity::getType, LikeRelationTypeEnum.BLOG.getValue())
                .eq(CollectEntity::getRelationId,blogId);
        Long collectCount = collectMapper.selectCount(countWrapper);
        if(collectCount>0){
            res.setIsCollect(CommonEnum.YES.getValue());
        }else {
            res.setIsCollect(CommonEnum.NO.getValue());
        }
        return res;
    }

    @Override
    public Page<PageBlogRes> userCenterPageBlog(PageBlogReq req) {
        Integer userId = SecurityUtils.getUserId();
        Page page = new Page(req.getPageNum(),req.getPageSize());
        Page<PageBlogRes> result = this.getBaseMapper().userCenterPageBlog(req,userId,page);
        return result;
    }

    @Override
    public void likeBlog(Integer blogId) {
        unviewBlog(blogId);
        BlogEntity blog = this.getById(blogId);


        Integer userId = SecurityUtils.getUserId();
        QueryWrapper<LikeEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(LikeEntity::getType,LikeRelationTypeEnum.BLOG.getValue())
                .eq(LikeEntity::getRelationId,blogId)
                .eq(LikeEntity::getUserId,userId);
        LikeEntity entity = likeMapper.selectOne(wrapper);
        if(entity!=null){
            likeMapper.deleteById(entity);
            blog.setLikeCount(blog.getLikeCount()-1);
            saveOrUpdate(blog);
        }else {
            LikeEntity like = new LikeEntity();
            like.setType(LikeRelationTypeEnum.BLOG.getValue());
            like.setUserId(userId);
            like.setRelationId(blogId);
            likeMapper.insert(like);
            blog.setLikeCount(blog.getLikeCount()+1);
            saveOrUpdate(blog);
        }
    }

    @Override
    public void collectBlog(Integer blogId) {
        unviewBlog(blogId);
        BlogEntity blog = this.getById(blogId);

        Integer userId = SecurityUtils.getUserId();
        QueryWrapper<CollectEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(CollectEntity::getType,LikeRelationTypeEnum.BLOG.getValue())
                .eq(CollectEntity::getRelationId,blogId)
                .eq(CollectEntity::getUserId,userId);
        CollectEntity entity = collectMapper.selectOne(wrapper);
        if(entity!=null){
            collectMapper.deleteById(entity);
            blog.setCollectCount(blog.getCollectCount()+-1);
            saveOrUpdate(blog);
        }else {
            CollectEntity collect = new CollectEntity();
            collect.setType(LikeRelationTypeEnum.BLOG.getValue());
            collect.setUserId(userId);
            collect.setRelationId(blogId);
            collectMapper.insert(collect);
            blog.setCollectCount(blog.getCollectCount()+1);
            saveOrUpdate(blog);
        }
    }


    private void viewBlog(Integer blogId){
        BlogEntity blog = this.getBaseMapper().selectById(blogId);
        blog.setViewCount(blog.getViewCount()+1);
        saveOrUpdate(blog);
    }

    private void unviewBlog(Integer blogId){
        BlogEntity blog = this.getBaseMapper().selectById(blogId);
        blog.setViewCount(blog.getViewCount()-1);
        saveOrUpdate(blog);
    }

}
